package com.wsoft.bpm.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.pagehelper.PageHelper;
import com.wsoft.bpm.bean.ActModelMetaInfo;
import com.wsoft.bpm.dto.ActModelDTO;
import com.wsoft.bpm.dto.ActProcessDTO;
import com.wsoft.bpm.entity.ActWorkflowConfigEntity;
import com.wsoft.bpm.mapper.ActProcessMapper;
import com.wsoft.bpm.service.ActProcessService;
import com.wsoft.bpm.service.IActReModelService;
import com.wsoft.bpm.service.IActWorkflowConfigService;
import com.wsoft.bpm.vo.ProcessListVO;
import com.wsoft.constant.CommonConstant;
import com.wsoft.core.exception.Asserts;
import com.wsoft.entity.BaseEntity;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Model;
import org.activiti.engine.repository.ProcessDefinition;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * @Author zhonglj
 * @Date 2024-08-28 15:20
 */
@Slf4j
@Service
public class ActProcessServiceImpl implements ActProcessService {
    @Resource
    private ActProcessMapper actProcessMapper;
    @Resource
    private RepositoryService repositoryService;
    @Resource
    private IActWorkflowConfigService actWorkflowConfigService;
    @Resource
    private IActReModelService actReModelService;

    @Override
    public Page<ProcessListVO> pageList(ActProcessDTO dto) {
        return actProcessMapper.pageList(new Page(dto.getPageNum(), dto.getPageSize()), dto);
    }

    @Override
    public Boolean resetModel(String deploymentId, String fileName) {
        // 获取部署xml数据流
        byte[] xmlData = getXmlData(deploymentId, fileName);

        if (xmlData != null) {
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult();
            List<ActWorkflowConfigEntity> targetVersionConfig = actWorkflowConfigService.list(
                    Wrappers.lambdaQuery(ActWorkflowConfigEntity.class)
                            .eq(BaseEntity::getDeleted, CommonConstant.YESNO_NO)
                            .eq(ActWorkflowConfigEntity::getProcDefId, processDefinition.getId())
            );

            if (CollUtil.isEmpty(targetVersionConfig)) {
                log.error("未查询到对应的json配置!");
                return false;
            }

            // 映射生成一个新的模型
            String modelId = targetVersionConfig.get(0).getModelId();
            Model targetModel = repositoryService.createModelQuery().modelId(modelId).singleResult();
            ActModelMetaInfo modelMetaInfo = JSONUtil.toBean(targetModel.getMetaInfo(), ActModelMetaInfo.class);
            ActModelDTO modelDTO = new ActModelDTO();
            modelDTO.setKey(targetModel.getKey());
            modelDTO.setCategory(targetModel.getCategory());
            modelDTO.setName("[映射]" + targetModel.getName());
            modelDTO.setDesc(modelMetaInfo.getDescription());
            String resetModelId = actReModelService.createModel(modelDTO);

            // 更新模型xml数据
            repositoryService.addModelEditorSource(resetModelId, xmlData);
            // 保存json数据到新模型
            targetVersionConfig.stream().forEach(e -> {
                e.setId(null);
                e.setModelId(resetModelId);
                e.setProcDefId(null);
            });
            actWorkflowConfigService.saveBatch(targetVersionConfig);

            return true;
        }

        return false;
    }

    @Override
    public String xmlView(String deploymentId, String fileName) {
        byte[] xmlData = getXmlData(deploymentId, fileName);
        if (xmlData != null) {
            return new String(xmlData, StandardCharsets.UTF_8);
        }
        return "";
    }

    @Override
    public void suspend(String processDefinitionId) {
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
        if (processDefinition != null) {
            // 查看是否可以挂起
            boolean suspended = processDefinition.isSuspended();
            if (suspended) {
                Asserts.fail("[bpm.process.error.suspend.suspended]");
            }
            repositoryService.suspendProcessDefinitionById(processDefinitionId);
        }

    }

    @Override
    public void active(String processDefinitionId) {
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
        if (processDefinition != null) {
            // 查看是否可以激活
            boolean suspended = processDefinition.isSuspended();
            if (!suspended) {
                Asserts.fail("[bpm.process.error.active.activated]");
            }
            repositoryService.activateProcessDefinitionById(processDefinitionId);
        }
    }

    /**
     * 获取指定版本的xml数据
     *
     * @param deploymentId
     * @param fileName
     * @return byte[]
     * @author zhonglj
     * @date 2024/11/20 14:49
     **/
    private byte[] getXmlData(String deploymentId, String fileName) {
        List<String> names = repositoryService.getDeploymentResourceNames(deploymentId);
        byte[] xmlData = null;
        for (String name : names) {
            if (StrUtil.endWith(name, ".zip")) {
                continue;
            }
            if (StrUtil.contains(name, fileName)) {
                InputStream in = repositoryService.getResourceAsStream(deploymentId, name);
                xmlData = IoUtil.readBytes(in, true);
                break;
            }
        }

        return xmlData;
    }
}
